
#ifdef __cplusplus
	extern "C" 
	{
#endif
	#include <avr/io.h>
	#include <stdbool.h>
#ifdef __cplusplus
	}
#endif

#include "BInit_328P.hpp"
#include "Ports.hpp"
#include "CDef.hpp"
/*
 * BInit_328P.c
 *
 * Created: 30/06/2014 7:35:24 PM
 *  Author: MacGyver
 */ 
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};
void __cxa_pure_virtual(void) {};
void * operator new(size_t size) 
{ 
	void * pvPTR = malloc(size);
	
	if(pvPTR != nullptr)	{ return pvPTR; }
	else					{ while(1) {} }
}
void operator delete(void * ptr) { free(ptr); }
	
int freeram() 
{
	extern int __heap_start, *__brkval;
	int v;
	return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
	
#define NO_IO_PORTS_A328P		3u
#define TO_ASCII				+ 0x30u
#define BOARD_VERSION_MAJOR		1u TO_ASCII	/* vX.- */
#define BOARD_VERSION_MINOR		0u TO_ASCII	/* v-.X */
#define BOARD_NO_OF_RELAY		4u TO_ASCII
#define BOARD_NO_OF_PWM			4u TO_ASCII
#define BOARD_NO_OF_INPUT		6u TO_ASCII
#define BOARD_NO_OF_ADC			2u TO_ASCII
const uint8_t BINI::au8BOARD_SERIAL[11] = {'v', BOARD_VERSION_MAJOR, BOARD_VERSION_MINOR, 'R', BOARD_NO_OF_RELAY, 'P', BOARD_NO_OF_PWM, 'I', BOARD_NO_OF_INPUT, 'A', BOARD_NO_OF_ADC};

/************************************************
* PORTs address.
*************************************************/
static volatile uint8_t * pu8PORTAddress[NO_IO_PORTS_A328P] =
{
	&PORTB,
	&PORTC,
	&PORTD
};

/************************************************
* PORTs to configure. 
*	0 = Don't touch
*	1 = Touch
*************************************************/
static unsigned char u8PORTs[NO_IO_PORTS_A328P] =
{/* Bit   76543210 */
		0b00011101,	/* Port B - */
		0b00111111,	/* Port C - */
		0b11111100	/* Port D - */
};

/************************************************
* PORTs Direction
*	0 = Input
*	1 = Output
*************************************************/
static unsigned char BINI_u8PORTDirection[NO_IO_PORTS_A328P] =
{/* Bit   76543210 */
		0b00011100,	/* Port B - */
		0b00011111,	/* Port C - */
		0b01001000	/* Port D - */
};

/************************************************
* PORTs Pullup/Level
*	INPUT  - x = Pull-up Enable
*	OUTPUT - x = Port Level
*************************************************/
static unsigned char BINI_u8PORTPullUp[NO_IO_PORTS_A328P] =
{/* Bit   76543210 */
		0b00000001,	/* Port B - */
		0b00100000,	/* Port C - */
		0b10110100	/* Port D - */
};

void BINI::vInitPorts(void)
{
	PORT * mPORTs[NO_IO_PORTS_A328P];
	unsigned char u8PIN, u8PORT;
	
	u8PORT = 0;
	for(PORT * p : mPORTs)
	{
		p = new PORT(pu8PORTAddress[u8PORT]);
		
		u8PIN = 0;
		for(PIN * pin : p->PINs)
		{
			if(((u8PORTs[u8PORT] & (1<<pin->u8Bit)) >> pin->u8Bit) == 1)
			{
				/* Set Port Direction */
				pin->vSetDirection((BINI_u8PORTDirection[u8PORT] & (1<<pin->u8Bit)) ? PIN::OUTPUT : PIN::INPUT);
				
				/* Set Port Pull-up or Level */
				pin->vSetPullUp((BINI_u8PORTPullUp[u8PORT] & (1<<pin->u8Bit)) ? PIN::ON : PIN::OFF);
			}
			u8PIN++;
		}	
		u8PORT++;	
		
		delete p;
	}
}
